package com.zhs.gccs.utils;

import android.util.Log;

import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.AesKeyStrength;
import net.lingala.zip4j.model.enums.EncryptionMethod;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;




public class ZipUtils {

    public static final String TAG = ZipUtils.class.getSimpleName();

    /**
     * 解压缩文件
     *
     * @param zipPath         压缩包文件路径
     * @param outputDirectory 解压到的目录
     * @throws IOException
     */
    public static Boolean unzipFile(String zipPath, String outputDirectory) throws IOException {
        Log.i(TAG, "开始解压的文件： " + zipPath + "\n" + "解压的目标路径：" + outputDirectory);
        // 创建解压目标目录
        File file = new File(outputDirectory);
        // 如果目标目录不存在，则创建
        if (!file.exists()) {
            file.mkdirs();
        }
        // 打开压缩文件
        InputStream inputStream = new FileInputStream(zipPath);
        ;
        ZipInputStream zipInputStream = new ZipInputStream(inputStream);

        // 读取一个进入点
        ZipEntry zipEntry = zipInputStream.getNextEntry();
        // 使用1Mbuffer
        byte[] buffer = new byte[1024 * 1024];
        // 解压时字节计数
        int count = 0;
        // 如果进入点为空说明已经遍历完所有压缩包中文件和目录
        while (zipEntry != null) {
            Log.i(TAG, "解压文件 入口 1： " + zipEntry);
            if (!zipEntry.isDirectory()) {  //如果是一个文件
                // 如果是文件
                String fileName = zipEntry.getName();
                Log.i(TAG, "解压文件 原来 文件的位置： " + fileName);
                fileName = fileName.substring(fileName.lastIndexOf("/") + 1);  //截取文件的名字 去掉原文件夹名字
                Log.i(TAG, "解压文件 的名字： " + fileName);
                file = new File(outputDirectory + File.separator + fileName);  //放到新的解压的文件路径

                file.createNewFile();
                FileOutputStream fileOutputStream = new FileOutputStream(file);
                while ((count = zipInputStream.read(buffer)) > 0) {
                    fileOutputStream.write(buffer, 0, count);
                }
                fileOutputStream.close();

            }

            // 定位到下一个文件入口
            zipEntry = zipInputStream.getNextEntry();
            Log.i(TAG, "解压文件 入口 2： " + zipEntry);
        }
        zipInputStream.close();
        Log.i(TAG, "解压完成");
        return true;
    }

    public static void unzipFile(InputStream inputStream0, String outputDirectory) throws IOException {
        Log.i(TAG, "解压的目标路径：" + outputDirectory);
        // 创建解压目标目录
        File file = new File(outputDirectory);
        // 如果目标目录不存在，则创建
        if (!file.exists()) {
            file.mkdirs();
        }
        // 打开压缩文件
        InputStream inputStream = inputStream0;
        ;
        ZipInputStream zipInputStream = new ZipInputStream(inputStream);
        // 读取一个进入点
        ZipEntry zipEntry = zipInputStream.getNextEntry();
        // 使用1Mbuffer
        byte[] buffer = new byte[1024 * 1024];
        // 解压时字节计数
        int count = 0;
        // 如果进入点为空说明已经遍历完所有压缩包中文件和目录
        while (zipEntry != null) {
//            Log.i(TAG,"解压文件 入口 1： " +zipEntry );
            if (!zipEntry.isDirectory()) {  //如果是一个文件
                // 如果是文件
                String fileName = zipEntry.getName();
                Log.i(TAG, "解压文件 原来 文件的位置： " + fileName);
//                Log.i(TAG,"解压文件 的名字： " + fileName);
                String[] folders = fileName.split("/");
//                fileName = fileName.substring(fileName.lastIndexOf("/") + 1);  //截取文件的名字 去掉原文件夹名字
                int length = folders.length;
                String genPath = outputDirectory;
                int i = 0;
                for (String folder : folders) {
                    if (i < length - 1) {
                        genPath = genPath + folder + "/";
                        file = new File(genPath);
                        if (!file.exists()) {
                            file.mkdir();
                            Log.i(TAG, "创建文件夹 " + genPath);
                        } else {
                            Log.i(TAG, "已存在文件夹 " + genPath);
                        }
                    } else {
                        file = new File(genPath, folder);
                        if (!file.isFile()) {
                            file.createNewFile();
                            Log.i(TAG, "创建文件 " + folder);
                        } else {
                            Log.i(TAG, "已存在文件 " + folder);
                        }
                    }

                    i++;
                }

                FileOutputStream fileOutputStream = new FileOutputStream(file);
                while ((count = zipInputStream.read(buffer)) > 0) {
                    fileOutputStream.write(buffer, 0, count);
                }
                fileOutputStream.close();

            }

            // 定位到下一个文件入口
            zipEntry = zipInputStream.getNextEntry();
//            Log.i(TAG,"解压文件 入口 2： " + zipEntry );
        }
        zipInputStream.close();
        Log.i(TAG, "解压完成");
        CacheUtils.getInstance().removePathFromList();

    }

    public static boolean compressToZip(String sourceFilePath, String destFile) {
        File sourceFile = new File(sourceFilePath);
        File zipFile = new File(destFile);
        if (!zipFile.getParentFile().exists()) {
            zipFile.getParentFile().mkdirs();
        }
        try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile))) {
            writeZip(sourceFile, "", zos);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage(), e.getCause());
        }
    }
    /**
     * 压缩文件
     *
     * @param sourceFilePath 源文件路径
     * @param zipFilePath    压缩后文件存储路径
     * @param zipFilename    压缩文件名
     */
    public static boolean compressToZip(String sourceFilePath, String zipFilePath, String zipFilename) {
        File sourceFile = new File(sourceFilePath);
        File zipPath = new File(zipFilePath);
        if (!zipPath.exists()) {
            zipPath.mkdirs();
        }
        File zipFile = new File(zipPath + File.separator + zipFilename);
        try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile))) {
            writeZip(sourceFile, "", zos);
            //文件压缩完成后，删除被压缩文件
//            boolean flag = deleteDir(sourceFile);
//            log.info("删除被压缩文件[" + sourceFile + "]标志：{}", flag);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage(), e.getCause());
        }
    }

    /**
     * 遍历所有文件，压缩
     *
     * @param file       源文件目录
     * @param parentPath 压缩文件目录
     * @param zos        文件流
     */
    public static void writeZip(File file, String parentPath, ZipOutputStream zos) {
        if (file.isDirectory()) {
            //目录
            parentPath += file.getName() + File.separator;
            File[] files = file.listFiles();
            for (File f : files) {
                writeZip(f, parentPath, zos);
            }
        } else {
            //文件
            try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file))) {
                //指定zip文件夹
                ZipEntry zipEntry = new ZipEntry(parentPath + file.getName());
                zos.putNextEntry(zipEntry);
                int len;
                byte[] buffer = new byte[1024 * 10];
                while ((len = bis.read(buffer, 0, buffer.length)) != -1) {
                    zos.write(buffer, 0, len);
                    zos.flush();
                }
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException(e.getMessage(), e.getCause());
            }
        }
    }

    /**
     * 删除文件夹
     *
     * @param dir
     * @return
     */
    public static boolean deleteDir(File dir) {
        if (dir.isDirectory()) {
            String[] children = dir.list();
            for (int i = 0; i < children.length; i++) {
                boolean success = deleteDir(new File(dir, children[i]));
                if (!success) {
                    return false;
                }
            }
        }
        //删除空文件夹
        return dir.delete();
    }

    public static String getZipPath(String path) {
        File file = new File(path);
        if (file.exists()) {
            File[] files = file.listFiles();
            if (null != files) {
                for (File file2 : files) {
                    if (!file2.isDirectory()) {
                        if (file2.getAbsolutePath().endsWith(".zip")) {
                            Log.e("kxp", "zip路径" + file2.getAbsolutePath());
                            return file2.getAbsolutePath();
                        }
                    }
                }
            }
            return null;
        } else {
            Log.e("kxp", "无文件解压");
            return null;
        }
    }


    public static void unZIP(String entryFile) throws IOException {
        File file = new File(entryFile);

        ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(file)));

        File fout = null;
        String parent = file.getParent();
        ZipEntry entry;
        while((entry = zis.getNextEntry())!=null && !entry.isDirectory()){
            fout = new File(parent, entry.getName());
            if(!fout.exists()){
                (new File(fout.getParent())).mkdirs();
            }

            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(fout));

            int b = -1;
            byte[] buffer = new byte[1024];
            while((b = zis.read(buffer))!= -1){
                bos.write(buffer, 0, b);
            }
            bos.close();
        }

        zis.close();

  }

    public static void zip(List<File> srcFiles,
                           String zipPath,String password) throws ZipException {
        zip(srcFiles, new File(zipPath), password);
    }

    public static void zip(List<File> srcFiles,
                           File zipPath,String password) throws ZipException {
        if(password==null)return;
        ZipParameters zipParameters = new ZipParameters();
        zipParameters.setEncryptFiles(true);
        zipParameters.setEncryptionMethod(EncryptionMethod.AES);
        // Below line is optional. AES 256 is used by default. You can override it to use AES 128. AES 192 is supported only for extracting.
        zipParameters.setAesKeyStrength(AesKeyStrength.KEY_STRENGTH_256);

        ZipParameters zipFileParameters = new ZipParameters();
        zipFileParameters.setEncryptFiles(true);
        zipFileParameters.setEncryptionMethod(EncryptionMethod.AES);
        // Below line is optional. AES 256 is used by default. You can override it to use AES 128. AES 192 is supported only for extracting.
        zipFileParameters.setAesKeyStrength(AesKeyStrength.KEY_STRENGTH_256);
        zipFileParameters.setIncludeRootFolder(false);

        ZipFile zipFile = new ZipFile(zipPath, password.toCharArray());

        for(int i=0;i<srcFiles.size();i++){
            File subFile = srcFiles.get(i);
            if(subFile.isFile()){
                zipFile.addFile(subFile, zipFileParameters);
            }else if(subFile.isDirectory()){
                zipFile.addFolder(subFile, zipParameters);
            }
        }
    }

    /**
     *
     * @param srcPath  源文件
     * @param destZipFilePath
     * @param withSrcDir  如果源文件是文件夹是否把该作为第一层压缩
     * @param password  压缩密码
     * @throws IOException
     */
    public static boolean zip(String srcPath, String destZipFilePath,
                              boolean withSrcDir ,String password) {
        try{
            ZipParameters zipParameters = new ZipParameters();
            if(password==null){
                zipParameters.setEncryptFiles(false);
            }else {
                zipParameters.setEncryptFiles(true);
            }
            zipParameters.setEncryptionMethod(EncryptionMethod.AES);
            // Below line is optional. AES 256 is used by default. You can override it to use AES 128. AES 192 is supported only for extracting.
            zipParameters.setAesKeyStrength(AesKeyStrength.KEY_STRENGTH_256);

            ZipFile zipFile = new ZipFile(destZipFilePath, password!=null?password.toCharArray():null);
//            zipFile.setRunInThread(true);
            File srcFile = new File(srcPath);
            if(withSrcDir){
                if(srcFile.isFile()){
                    zipFile.addFile(srcFile, zipParameters);
                }else if(srcFile.isDirectory()){
                    zipFile.addFolder(srcFile, zipParameters);
                }
            }if(srcFile.isFile()){
                zipFile.addFile(srcFile, zipParameters);
            }else if(srcFile.isDirectory()){
                File[] subFiles = srcFile.listFiles();
                for(int i=0;i<subFiles.length;i++){
                    File subFile = subFiles[i];
                    if(subFile.isFile()){
                        zipFile.addFile(subFile, zipParameters);
                    }else if(subFile.isDirectory()){
                        zipFile.addFolder(subFile, zipParameters);
                    }
                }
            }
//            ProgressMonitor progressMonitor = zipFile.getProgressMonitor();
            return true;
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }
    public static void unzip(String zipFilePath, String outFileDir,String password) throws ZipException {
        ZipFile zipFile = new ZipFile(zipFilePath, password.toCharArray());
        zipFile.extractAll(outFileDir);
    }
    public static void unzip(String zipFilePath, String outFileDir) throws ZipException {
        ZipFile zipFile = new ZipFile(zipFilePath);
        zipFile.extractAll(outFileDir);
    }

    public static void main(String[] args) {
        try {
            zip("C:\\Users\\renweiwei\\Desktop\\2023年4月湖北省老河口市、荆州区高标准农田核查_04869920928e4f61a6145ef745dc2931",
                    "C:\\Users\\renweiwei\\Desktop\\ruoyi222222.zip",false, "111111");
//            unzip("G:/ruoyi222222.zip","G:/ruoyi333333", "111111");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
